#include "kittingcell.h"
#include "AnimationView.h"
#include "MessageLogEntry.h"
#include "GUILane.h"
#include "GUINest.h"
#include "GUIConveyor.h"
#include "GUICamera.h"
#include "GUIKitRobot.h"
#include "TraceManager.h"
#include <qgraphicsscene.h>
#include <qlist.h>
#include <qstring.h>
#include <qchar.h>
#include <string>
#include <qdebug.h>
#include <Kit.h>
#include <qpixmap.h>

#include "ScopedLock.h"

class GUIGantry;
class GUIPartRobot;
class PartRobot;
using std::string;
using std::vector;

KittingCell::KittingCell(QWidget *parent, Qt::WFlags flags) 
	: QMainWindow(parent, flags)
{
	srand ( time(NULL) ); // Seed random function.

	ui.setupUi(this);
	factoryScene = new AnimationView(ui.graphicsView);
	ui.graphicsView->setScene(factoryScene);
	GUIBase::factoryScene = factoryScene;

	timer = new QTimer();
	timer->setInterval(33);
	connect(timer, SIGNAL(timeout()), this, SLOT(timerSlot()));

	//table instantiation 
	table= new Table(200, 360, "mytable", factoryScene);
	qDebug() << "testing table output";
	//qDebug() << table->TABLE_X; 
	//qDebug() << table->TABLE_Y;
	//qDebug() << table->getTableSlotPosition(0);
	//qDebug() << table->getTableSlotPosition(1);
	//qDebug() << table->getTableSlotPosition(2);



		/* GRAHAM MATUSZEWSKI 
		HEY 200 PEOPLE
			dont touch this stuff seriously

	//*/
	//GantryAgent* gantryAgent=new GantryAgent("Gantry");
	//FeederAgent* feederAgent1=new FeederAgent("Feeder One");
	////FeederAgent feederAgent1("Feeder Two");
	////FeederAgent feederAgent1("Feeder Three");
	////FeederAgent feederAgent1("Feeder Four");
	//LaneAgent* laneAgent1= new LaneAgent("Lane One");
	////LaneAgent laneAgent2("Lane Two");
	//NestAgent* nestAgent1= new NestAgent("Nest One");

	//gantryAgent->setFeeder1(feederAgent1);
	//gantryAgent->setFeeder2(feederAgent1);
	//gantryAgent->setFeeder3(feederAgent1);
	//gantryAgent->setFeeder4(feederAgent1);
	//feederAgent1->setLaneTop(laneAgent1);
	//feederAgent1->setLaneBottom(laneAgent1);
	//feederAgent1->setGantry(gantryAgent);
	//laneAgent1->setFeeder(feederAgent1);
	//laneAgent1->setNest(nestAgent1);

	//PartType p=A;
	//laneAgent1->msgPleaseGetParts(p);

	//FeederAgent feederAgent2("Gantry");
	

	FCSAgent = new FactoryControlSystemAgent("Factory Control System");
	FCSAgent->setMainWindow(this);
	agents.push_back(FCSAgent);

	inConveyorAgent = new ConveyorAgent("In Conveyor", Conveyor_In);
	agents.push_back(inConveyorAgent);
	outGoodConveyorAgent  = new ConveyorAgent("Out Good Conveyor", Conveyor_OutGood);
	agents.push_back(outGoodConveyorAgent);
	outBadConveyorAgent  = new ConveyorAgent("Out Bad Conveyor", Conveyor_OutBad);
	agents.push_back(outBadConveyorAgent);

	kitRobotAgent = new KitRobotAgent("Kit Robot");
	agents.push_back(kitRobotAgent);

	inspectorAgent = new InspectorAgent("Inspector");
	agents.push_back(inspectorAgent);

	partRobotAgent = new PartRobotAgent("Part Robot");
	gantryAgent=new GantryAgent("Gantry");
	agents.push_back(gantryAgent);

	partSorterUnitsAgents = new PartSorterUnit* [numOfPartSorterUnits];

	PartSorterUnit* partSorter;
	for(int i = 0; i < numOfPartSorterUnits; i++)
	{
		partSorter = new PartSorterUnit(0);

		agents.push_back(partSorter->cameraAgent);
		agents.push_back(partSorter->feederAgent);
		agents.push_back(partSorter->lane1Agent);
		agents.push_back(partSorter->lane2Agent);
		agents.push_back(partSorter->nest1Agent);
		agents.push_back(partSorter->nest2Agent);

		partSorter->setGantry(this->gantryAgent);
		partSorter->setPartRobot((PartRobot*)this->partRobotAgent);

		partSorterUnitsAgents[i] = partSorter;
	}


	FCSAgent->setConveyor(inConveyorAgent);

	inConveyorAgent->setFCS(FCSAgent);
	inConveyorAgent->setKitRobot(kitRobotAgent);

	outGoodConveyorAgent->setFCS(FCSAgent);
	outGoodConveyorAgent->setKitRobot(kitRobotAgent);

	outBadConveyorAgent->setFCS(FCSAgent);
	outBadConveyorAgent->setKitRobot(kitRobotAgent);

	kitRobotAgent->SetInspector(this->inspectorAgent);
	kitRobotAgent->SetOnConveyor(inConveyorAgent);
	kitRobotAgent->SetOffBadConveyor(outBadConveyorAgent);
	kitRobotAgent->SetOffGoodConveyor(outGoodConveyorAgent);
	kitRobotAgent->SetPartsRobot((PartRobot*)this->partRobotAgent);
	kitRobotAgent->SetTable(table);

	inspectorAgent->SetKitRobot(kitRobotAgent);
	inspectorAgent->SetTable(table);

	partRobotAgent->setKitRobot(kitRobotAgent);
	partRobotAgent->setTable(table);
	for(int i = 0; i < numOfPartSorterUnits; i++) {
		partRobotAgent->addNest(partSorterUnitsAgents[i]->nest1Agent);
		partRobotAgent->addNest(partSorterUnitsAgents[i]->nest2Agent);
	}

	gantryAgent->setFeeder1(partSorterUnitsAgents[0]->feederAgent);
	gantryAgent->setFeeder2(partSorterUnitsAgents[1]->feederAgent);
	gantryAgent->setFeeder3(partSorterUnitsAgents[2]->feederAgent);
	gantryAgent->setFeeder4(partSorterUnitsAgents[3]->feederAgent);


	/* realyy dont touch stuff above here 


	...Im cerial
	*/



	// -------------------------------------------------------------------------------------------------------------------------------------------------------
	// Alex says: The below should really be handled algorithmically inside a struct (probably PartSorterUnit), using formulas to define the coordinates based on index

	// Open/close signs
	pixOpenSign = new QGraphicsPixmapItem(QPixmap("Resources/Sprites/OpenSign.png"));
	pixOpenSign->setX(250);
	pixOpenSign->setY(20);
	pixOpenSign->hide();
	factoryScene->addItem(pixOpenSign);

	pixClosedSign = new QGraphicsPixmapItem(QPixmap("Resources/Sprites/ClosedSign.png"));
	pixClosedSign->setX(250);
	pixClosedSign->setY(20);
	factoryScene->addItem(pixClosedSign);

	#define	FEEDER_X 810

	//top (zeroth) set of lanes 	
	GUINest* nest0 = new GUINest(400, 20, NestColor_Yellow);
	GUILane* lane0 = new GUILane(450, 20, 50, nest0, LaneColor_Yellow);
	GUINest* nest1 = new GUINest(400, 66, NestColor_Yellow);
	GUILane* lane1 = new GUILane(450, 66, 50, nest1, LaneColor_Yellow);
	feeders.push_back(new GUIFeeder(FEEDER_X, 68, partSorterUnitsAgents[0]->feederAgent, lane0, lane1, 0, FeederColor_Yellow));
	lanes.push_back(lane0);
	lanes.push_back(lane1);
	nests.push_back(nest0);
	nests.push_back(nest1);

	nest0->setAgent(this->partSorterUnitsAgents[0]->nest1Agent);
	nest1->setAgent(this->partSorterUnitsAgents[0]->nest2Agent);
	lane0->setAgent(this->partSorterUnitsAgents[0]->lane1Agent);
	lane1->setAgent(this->partSorterUnitsAgents[0]->lane2Agent);
	feeders.at(0)->setAgent(this->partSorterUnitsAgents[0]->feederAgent);

	lane0->setNeighbor(lane1);
	lane1->setNeighbor(lane0);

	partSorterUnitsAgents[0]->feederAgent->setGUIFeeder(feeders.at(0));

	partSorterUnitsAgents[0]->nest1Agent->setGUI(nest0);
	partSorterUnitsAgents[0]->nest2Agent->setGUI(nest1);

	partSorterUnitsAgents[0]->lane1Agent->setGUI(lane0);
	partSorterUnitsAgents[0]->lane2Agent->setGUI(lane1);



	//next set (first)
	GUINest* nest2 = new GUINest(400, 130, NestColor_Green);
	GUILane* lane2 = new GUILane(450, 130, 50, nest2, LaneColor_Green);
	GUINest* nest3 = new GUINest(400, 176, NestColor_Green);
	GUILane* lane3 = new GUILane(450, 176, 50, nest3, LaneColor_Green);
	feeders.push_back(new GUIFeeder(FEEDER_X, 178, partSorterUnitsAgents[1]->feederAgent, lane2, lane3, 1, FeederColor_Green));
	lanes.push_back(lane2);
	lanes.push_back(lane3);
	nests.push_back(nest2);
	nests.push_back(nest3);

	nest2->setAgent(this->partSorterUnitsAgents[0]->nest1Agent);
	nest3->setAgent(this->partSorterUnitsAgents[0]->nest2Agent);
	lane2->setAgent(this->partSorterUnitsAgents[0]->lane1Agent);
	lane3->setAgent(this->partSorterUnitsAgents[0]->lane2Agent);
	feeders.at(1)->setAgent(this->partSorterUnitsAgents[1]->feederAgent);

	lane2->setNeighbor(lane3);
	lane3->setNeighbor(lane2);

	partSorterUnitsAgents[1]->feederAgent->setGUIFeeder(feeders.at(1));

	partSorterUnitsAgents[1]->nest1Agent->setGUI(nest2);
	partSorterUnitsAgents[1]->nest2Agent->setGUI(nest3);

	partSorterUnitsAgents[1]->lane1Agent->setGUI(lane2);
	partSorterUnitsAgents[1]->lane2Agent->setGUI(lane3);



	//second set of lanes 
	GUINest* nest4 = new GUINest(400, 240, NestColor_Purple);
	GUILane* lane4 = new GUILane(450, 240, 50, nest4, LaneColor_Purple);
	GUINest* nest5 = new GUINest(400, 286, NestColor_Purple);
	GUILane* lane5 = new GUILane(450, 286, 50, nest5, LaneColor_Purple);
	feeders.push_back(new GUIFeeder(FEEDER_X, 288, partSorterUnitsAgents[2]->feederAgent, lane4, lane5, 2, FeederColor_Purple));
	lanes.push_back(lane4);
	lanes.push_back(lane5);
	nests.push_back(nest4);
	nests.push_back(nest5);

	nest4->setAgent(this->partSorterUnitsAgents[0]->nest1Agent);
	nest5->setAgent(this->partSorterUnitsAgents[0]->nest2Agent);
	lane4->setAgent(this->partSorterUnitsAgents[0]->lane1Agent);
	lane5->setAgent(this->partSorterUnitsAgents[0]->lane2Agent);
	feeders.at(2)->setAgent(this->partSorterUnitsAgents[2]->feederAgent);

	lane4->setNeighbor(lane5);
	lane5->setNeighbor(lane4);

	partSorterUnitsAgents[2]->feederAgent->setGUIFeeder(feeders.at(2));

	partSorterUnitsAgents[2]->nest1Agent->setGUI(nest4);
	partSorterUnitsAgents[2]->nest2Agent->setGUI(nest5);

	partSorterUnitsAgents[2]->lane1Agent->setGUI(lane4);
	partSorterUnitsAgents[2]->lane2Agent->setGUI(lane5);


	//third set of lanes 
	GUINest* nest6 = new GUINest(400, 350, NestColor_Red);
	GUILane* lane6 = new GUILane(450, 350, 50, nest6, LaneColor_Red);
	GUINest* nest7 = new GUINest(400, 396, NestColor_Red);
	GUILane* lane7 = new GUILane(450, 396, 50, nest7, LaneColor_Red);
	feeders.push_back(new GUIFeeder(FEEDER_X, 398, partSorterUnitsAgents[3]->feederAgent, lane6, lane7, 3, FeederColor_Red));
	lanes.push_back(lane6);
	lanes.push_back(lane7);
	nests.push_back(nest6);
	nests.push_back(nest7);

	nest6->setAgent(this->partSorterUnitsAgents[0]->nest1Agent);
	nest7->setAgent(this->partSorterUnitsAgents[0]->nest2Agent);
	lane6->setAgent(this->partSorterUnitsAgents[0]->lane1Agent);
	lane7->setAgent(this->partSorterUnitsAgents[0]->lane2Agent);
	feeders.at(3)->setAgent(this->partSorterUnitsAgents[3]->feederAgent);

	lane6->setNeighbor(lane7);
	lane7->setNeighbor(lane6);
	
	partSorterUnitsAgents[3]->feederAgent->setGUIFeeder(feeders.at(3));

	partSorterUnitsAgents[3]->nest1Agent->setGUI(nest6);
	partSorterUnitsAgents[3]->nest2Agent->setGUI(nest7);

	partSorterUnitsAgents[3]->lane1Agent->setGUI(lane6);
	partSorterUnitsAgents[3]->lane2Agent->setGUI(lane7);

	//bin instatiation 
	vector<Bin*> bins;
	
	QPointF point;
	for (int i = 0; i < 8; i++)
	{
		point = GUIGantry::GetBinLocation(i);
		bins.push_back(new Bin(point.x(), point.y(), (BinColor)i));
	}

	//conveyor instatiation
	conveyorIn= new GUIConveyor(20, -10, Conveyor_In);
	GUIConveyor* conveyorOutG= new GUIConveyor(80, -10 , Conveyor_OutGood);
	GUIConveyor* conveyorOutB= new GUIConveyor(140, -10, Conveyor_OutBad);

	inConveyorAgent->setGUI(conveyorIn);
	outGoodConveyorAgent->setGUI(conveyorOutG);
	outBadConveyorAgent->setGUI(conveyorOutB);

	conveyorIn->setAgent(inConveyorAgent);
	conveyorOutG->setAgent(outGoodConveyorAgent);
	conveyorOutB->setAgent(outBadConveyorAgent);

	//camera instantiation
	GUICamera* camera0= new GUICamera(380, 46, factoryScene);
	GUICamera* camera1= new GUICamera(380, 156, factoryScene);
	GUICamera* camera2= new GUICamera(380, 266, factoryScene);
	GUICamera* camera3= new GUICamera(380, 376, factoryScene);
	GUICamera* inspectorCamera = new GUICamera(table->x() - 50, table->getTableSlotPosition(2).y(), factoryScene);

	cameras.push_back(camera0);
	cameras.push_back(camera1);
	cameras.push_back(camera2);
	cameras.push_back(camera3);
	cameras.push_back(inspectorCamera);

	partSorterUnitsAgents[0]->cameraAgent->setGUI(camera0);
	partSorterUnitsAgents[1]->cameraAgent->setGUI(camera1);
	partSorterUnitsAgents[2]->cameraAgent->setGUI(camera2);
	partSorterUnitsAgents[3]->cameraAgent->setGUI(camera3);
	
	this->inspectorAgent->SetGui(inspectorCamera);

	camera0->setAgent(this->partSorterUnitsAgents[0]->cameraAgent);
	camera1->setAgent(this->partSorterUnitsAgents[1]->cameraAgent);
	camera2->setAgent(this->partSorterUnitsAgents[2]->cameraAgent);
	camera3->setAgent(this->partSorterUnitsAgents[3]->cameraAgent);
	inspectorCamera->setAgent(inspectorAgent);

	
	// gantry instantiation
	gantryGUI = new GUIGantry(GANTRY_IDLE_X, GANTRY_IDLE_Y, factoryScene);
	gantryAgent->setGuiGantry(gantryGUI);
	gantryGUI->GiveBinList(bins);
	gantryGUI->GiveFeederList(feeders);
	gantryGUI->setAgent(gantryAgent);
	//gantry->DoGUIMoveToFeeder(2, 2);

	//robot instatiation
	partRobot = new GUIPartRobot(225, 50);
	partRobotAgent->setGUI(partRobot);
	partRobot->setHost((PartRobot*)partRobotAgent);
	
	kitRobot = new GUIKitRobot(80, 360);
	kitRobotAgent->SetGui(kitRobot);
	kitRobot->setAgent(kitRobotAgent);

	//roomba instantiation
	roomba = new GUIRoomba(ROOMBA_BASEX, ROOMBA_BASEY);


	//Give the agents a place to print messages to
	for(int i = 0; i < agents.size(); i++)
	{
		agents[i]->setTracePanel(tracePanelOutputs);
	}


	FCSAgent->start();

	inConveyorAgent->start();
	outGoodConveyorAgent->start();
	outBadConveyorAgent->start();

	kitRobotAgent->start();

	inspectorAgent->start();
	
	partRobotAgent->start();
	gantryAgent->start();

	for(int i = 0; i < numOfPartSorterUnits; i++) {
		partSorterUnitsAgents[i]->startAgents();
	}

	displayableMessageSenders = TraceManager::SharedManager()->displayableMessageSenders;

	for(int i = 0; i < agents.size(); i++)	//Activates everyone in the trace panel
	{
		bool addName = true;

		for(int j = 0; j < displayableMessageSenders->size(); j++)	//check to se if they are already in there
		{
			if(displayableMessageSenders->at(j) == agents[i]->getName())
			{
				addName = false;
				break;
			}
		}

		if(addName)
		{
			this->displayableMessageSenders->push_back(agents[i]->getName());
			qDebug() << agents[i]->getName().c_str() << endl;
		}

	}
	this->displayableMessageSenders->push_back(typeid(Part).name());
}

KittingCell::~KittingCell()
{
	delete timer;
}

void KittingCell::updateTracePanel()
{
	{
		//ScopedLock scopedPrintVectorLock(&printVectorLock);
		//ScopedLock scopedPrintVectorLock(&TraceManager::messageVectorLock);
		ScopedLock scopedPrintVectorLock(&TraceManager::SharedManager()->messageVectorLock);


		std::vector<MessageLogEntry*> *messageLog = TraceManager::SharedManager()->traceLog;
		std::vector<std::string> newMessageVector;

		//find new messages
		for(int i = 0; i < messageLog->size(); i++)
		{
			MessageLogEntry *entry = messageLog->at(i);

			if(entry->willBeDisplayed && !entry->isAlreadyDisplayed)
			{
				entry->isAlreadyDisplayed = true;

				QString qStringMsg;
				qStringMsg = QString::fromStdString(entry->getMessage());
				ui.tracePanel->append(qStringMsg);
			}
		}
	}
}

void KittingCell::filterTracePanel()
{
	std::vector<MessageLogEntry*> *messageLog = TraceManager::SharedManager()->traceLog;

	for(int i = 0; i < messageLog->size(); i++)
	{
		messageLog->at(i)->isAlreadyDisplayed = false;

		if(messageLog->at(i)->getSender()->messagesWillBeDisplayed)
		{
			messageLog->at(i)->willBeDisplayed = true;
		}
		else
		{
			messageLog->at(i)->willBeDisplayed = false;
		}

		/*
		for(int j = 0; j < this->displayableMessageSenders->size(); j++)
		{
			if(messageLog->at(i)->getSenderType() == displayableMessageSenders->at(j))
			{
				//then message can be displayed
				messageLog->at(i)->willBeDisplayed = true;
				break;
			}
		}
		*/
	}
	ui.tracePanel->clear();
	updateTracePanel();
}

void KittingCell::handleFCSTraceDisplayCheckbox(int state)
{
	if(state == Qt::Checked)
	{
		FCSAgent->messagesWillBeDisplayed = true;
	}
	else
	{
		FCSAgent->messagesWillBeDisplayed = false;
	}

	filterTracePanel();

	/*
	for(int i = 0; i < displayableMessageSenders->size(); i++)
	{
		if(displayableMessageSenders->at(i) == FCSAgent->getName())	//found it
		{
			if(state == Qt::Checked)	//should be displayed
			{
				return;
			}
			else	//shouldn't be displayed anymore
			{
				displayableMessageSenders->erase(displayableMessageSenders->begin() + i);
			}
		}

	}
	//haven't found it
	if(state == Qt::Unchecked)		//shouldn't be there
	{
		return;
	}
	else	//should be there
	{
		this->displayableMessageSenders->push_back(FCSAgent->getName());
	}
	filterTracePanel();
	*/
}

void KittingCell::handleConveyorTraceDisplayCheckbox(int state)
{

	if(state == Qt::Checked)
	{
		inConveyorAgent->messagesWillBeDisplayed = true;
		outGoodConveyorAgent->messagesWillBeDisplayed = true;
		outBadConveyorAgent->messagesWillBeDisplayed = true;

	}
	else
	{
		inConveyorAgent->messagesWillBeDisplayed = false;
		outGoodConveyorAgent->messagesWillBeDisplayed = false;
		outBadConveyorAgent->messagesWillBeDisplayed = false;
	}

	filterTracePanel();

	/*
	for(int i = 0; i < displayableMessageSenders->size(); i++)
	{
		if(displayableMessageSenders->at(i) == "In Conveyor" || displayableMessageSenders->at(i) == "Out Good Conveyor" || displayableMessageSenders->at(i) == "Out Bad Conveyor")	//found it
		{
			if(state == Qt::Checked)	//should be displayed
			{
				return;
			}
			else	//shouldn't be displayed anymore
			{
				displayableMessageSenders->erase(displayableMessageSenders->begin() + i);
			}
		}

	}
	//haven't found it
	if(state == Qt::Unchecked)		//shouldn't be there
	{
		return;
	}
	else	//should be there
	{
		this->displayableMessageSenders->push_back(inConveyorAgent->getName());
		this->displayableMessageSenders->push_back(outGoodConveyorAgent->getName());
		this->displayableMessageSenders->push_back(outBadConveyorAgent->getName());
	}
	filterTracePanel();
	*/
}

void KittingCell::handleKitRobotTraceDisplayCheckbox(int state)
{
	if(state == Qt::Checked)
	{
		kitRobotAgent->messagesWillBeDisplayed = true;
	}
	else
	{
		kitRobotAgent->messagesWillBeDisplayed = false;
	}

	filterTracePanel();


	/*
	for(int i = 0; i < displayableMessageSenders->size(); i++)
	{
		if(displayableMessageSenders->at(i) == kitRobotAgent->getName())	//found it
		{
			if(state == Qt::Checked)	//should be displayed
			{
				return;
			}
			else	//shouldn't be displayed anymore
			{
				displayableMessageSenders->erase(displayableMessageSenders->begin() + i);
			}
		}

	}
	//haven't found it
	if(state == Qt::Unchecked)		//shouldn't be there
	{
		return;
	}
	else	//should be there
	{
		this->displayableMessageSenders->push_back(kitRobotAgent->getName());
	}
	filterTracePanel();
	*/
}

void KittingCell::handleFeederTraceDisplayCheckbox(int state)
{
	if(state == Qt::Checked)
	{
		for(int i = 0; i < numOfPartSorterUnits; i++)
		{
			partSorterUnitsAgents[i]->feederAgent->messagesWillBeDisplayed = true;
		}
	}
	else
	{
		for(int i = 0; i < numOfPartSorterUnits; i++)
		{
			partSorterUnitsAgents[i]->feederAgent->messagesWillBeDisplayed = false;
		}
	}

	filterTracePanel();


	/*
	for(int i = 0; i < displayableMessageSenders->size(); i++)
	{
		if(displayableMessageSenders->at(i) == partSorterUnitsAgents[0]->feederAgent->getName())	//found it
		{
			if(state == Qt::Checked)	//should be displayed
			{
				return;
			}
			else	//shouldn't be displayed anymore
			{
				displayableMessageSenders->erase(displayableMessageSenders->begin() + i);
			}
		}

	}
	//haven't found it
	if(state == Qt::Unchecked)		//shouldn't be there
	{
		return;
	}
	else	//should be there
	{
		this->displayableMessageSenders->push_back(partSorterUnitsAgents[0]->feederAgent->getName());
	}
	filterTracePanel();
	*/
}

void KittingCell::handleLaneTraceDisplayCheckbox(int state)
{
	if(state == Qt::Checked)
	{
		for(int i = 0; i < numOfPartSorterUnits; i++)
		{
			partSorterUnitsAgents[i]->lane1Agent->messagesWillBeDisplayed = true;
			partSorterUnitsAgents[i]->lane2Agent->messagesWillBeDisplayed = true;
		}
	}
	else
	{
		for(int i = 0; i < numOfPartSorterUnits; i++)
		{
			partSorterUnitsAgents[i]->lane1Agent->messagesWillBeDisplayed = false;
			partSorterUnitsAgents[i]->lane2Agent->messagesWillBeDisplayed = false;
		}
	}

	filterTracePanel();

	/*
	for(int i = 0; i < displayableMessageSenders->size(); i++)
	{
		if(displayableMessageSenders->at(i) == partSorterUnitsAgents[0]->lane1Agent->getName())	//found it
		{
			if(state == Qt::Checked)	//should be displayed
			{
				return;
			}
			else	//shouldn't be displayed anymore
			{
				displayableMessageSenders->erase(displayableMessageSenders->begin() + i);
			}
		}

	}
	//haven't found it
	if(state == Qt::Unchecked)		//shouldn't be there
	{
		return;
	}
	else	//should be there
	{
		this->displayableMessageSenders->push_back(partSorterUnitsAgents[0]->lane1Agent->getName());
	}
	filterTracePanel();
	*/
}

void KittingCell::handleNestTraceDisplayCheckbox(int state)
{
	if(state == Qt::Checked)
	{
		for(int i = 0; i < numOfPartSorterUnits; i++)
		{
			partSorterUnitsAgents[i]->nest1Agent->messagesWillBeDisplayed = true;
			partSorterUnitsAgents[i]->nest2Agent->messagesWillBeDisplayed = true;
		}
	}
	else
	{
		for(int i = 0; i < numOfPartSorterUnits; i++)
		{
			partSorterUnitsAgents[i]->nest1Agent->messagesWillBeDisplayed = false;
			partSorterUnitsAgents[i]->nest2Agent->messagesWillBeDisplayed = false;
		}
	}

	filterTracePanel();

	/*
	for(int i = 0; i < displayableMessageSenders->size(); i++)
	{
		if(displayableMessageSenders->at(i) == partSorterUnitsAgents[0]->nest1Agent->getName())	//found it
		{
			if(state == Qt::Checked)	//should be displayed
			{
				return;
			}
			else	//shouldn't be displayed anymore
			{
				displayableMessageSenders->erase(displayableMessageSenders->begin() + i);
			}
		}

	}
	//haven't found it
	if(state == Qt::Unchecked)		//shouldn't be there
	{
		return;
	}
	else	//should be there
	{
		this->displayableMessageSenders->push_back(partSorterUnitsAgents[0]->nest1Agent->getName());
	}
	filterTracePanel();
	*/
}

void KittingCell::handleCameraTraceDisplayCheckbox(int state)
{
	if(state == Qt::Checked)
	{
		for(int i = 0; i < numOfPartSorterUnits; i++)
		{
			partSorterUnitsAgents[i]->cameraAgent->messagesWillBeDisplayed = true;
		}
	}
	else
	{
		for(int i = 0; i < numOfPartSorterUnits; i++)
		{
			partSorterUnitsAgents[i]->cameraAgent->messagesWillBeDisplayed = false;
		}
	}

	filterTracePanel();

	/*
	for(int i = 0; i < displayableMessageSenders->size(); i++)
	{
		if(displayableMessageSenders->at(i) == partSorterUnitsAgents[0]->cameraAgent->getName())	//found it
		{
			if(state == Qt::Checked)	//should be displayed
			{
				return;
			}
			else	//shouldn't be displayed anymore
			{
				displayableMessageSenders->erase(displayableMessageSenders->begin() + i);
			}
		}

	}
	//haven't found it
	if(state == Qt::Unchecked)		//shouldn't be there
	{
		return;
	}
	else	//should be there
	{
		this->displayableMessageSenders->push_back(partSorterUnitsAgents[0]->cameraAgent->getName());
	}
	filterTracePanel();
	*/
}

void KittingCell::handlePartRobotTraceDisplayCheckbox(int state)
{
	if(state == Qt::Checked)
	{
		for(int i = 0; i < numOfPartSorterUnits; i++)
		{
			partRobotAgent->messagesWillBeDisplayed = true;
		}
	}
	else
	{
		for(int i = 0; i < numOfPartSorterUnits; i++)
		{
			partRobotAgent->messagesWillBeDisplayed = false;
		}
	}

	filterTracePanel();

	/*
	for(int i = 0; i < displayableMessageSenders->size(); i++)
	{
		if(displayableMessageSenders->at(i) == partRobotAgent->getName())	//found it
		{
			if(state == Qt::Checked)	//should be displayed
			{
				return;
			}
			else	//shouldn't be displayed anymore
			{
				displayableMessageSenders->erase(displayableMessageSenders->begin() + i);
			}
		}

	}
	//haven't found it
	if(state == Qt::Unchecked)		//shouldn't be there
	{
		return;
	}
	else	//should be there
	{
		this->displayableMessageSenders->push_back(partRobotAgent->getName());
	}
	filterTracePanel();
	*/
}

void KittingCell::handleInspectorTraceDisplayCheckbox(int state)
{
	if(state == Qt::Checked)
	{
		for(int i = 0; i < numOfPartSorterUnits; i++)
		{
			inspectorAgent->messagesWillBeDisplayed = true;
		}
	}
	else
	{
		for(int i = 0; i < numOfPartSorterUnits; i++)
		{
			inspectorAgent->messagesWillBeDisplayed = false;
		}
	}

	filterTracePanel();

	/*
	for(int i = 0; i < displayableMessageSenders->size(); i++)
	{
		if(displayableMessageSenders->at(i) == inspectorAgent->getName())	//found it
		{
			if(state == Qt::Checked)	//should be displayed
			{
				return;
			}
			else	//shouldn't be displayed anymore
			{
				displayableMessageSenders->erase(displayableMessageSenders->begin() + i);
			}
		}

	}
	//haven't found it
	if(state == Qt::Unchecked)		//shouldn't be there
	{
		return;
	}
	else	//should be there
	{
		this->displayableMessageSenders->push_back(inspectorAgent->getName());
	}
	filterTracePanel();
	*/
}

void KittingCell::handleGantryTraceDisplayCheckbox(int state)
{
	if(state == Qt::Checked)
	{
		for(int i = 0; i < numOfPartSorterUnits; i++)
		{
			gantryAgent->messagesWillBeDisplayed = true;
		}
	}
	else
	{
		for(int i = 0; i < numOfPartSorterUnits; i++)
		{
			gantryAgent->messagesWillBeDisplayed = false;
		}
	}

	filterTracePanel();

	/*
	for(int i = 0; i < displayableMessageSenders->size(); i++)
	{
		if(displayableMessageSenders->at(i) == gantryAgent->getName())	//found it
		{
			if(state == Qt::Checked)	//should be displayed
			{
				return;
			}
			else	//shouldn't be displayed anymore
			{
				displayableMessageSenders->erase(displayableMessageSenders->begin() + i);
			}
		}

	}
	//haven't found it
	if(state == Qt::Unchecked)		//shouldn't be there
	{
		return;
	}
	else	//should be there
	{
		this->displayableMessageSenders->push_back(gantryAgent->getName());
	}
	filterTracePanel();
	*/
}


void KittingCell::timerSlot()
{
	this->updateTracePanel();
}

void KittingCell::startFactory()
{
	if(!factoryScene->isActive()) {
		qDebug() << "Starting Factory...";

		factoryScene->startAnimation();

		pixOpenSign->show();
		pixClosedSign->hide();

		timer->start();
	}
}

void KittingCell::pauseFactory()
{
	if(factoryScene->isActive()) {
		factoryScene->stopAnimation();

		
		pixOpenSign->hide();
		pixClosedSign->show();
	}
}

void KittingCell::stopFactory()
{
	pauseFactory();
}

void KittingCell::handleStartButton()
{
	this->startFactory();
}

void KittingCell::handlePauseButton()
{
	this->pauseFactory();
}

void KittingCell::handleStopButton()
{
	this->stopFactory();
}

void KittingCell::handleFactorySpeedSliderMoved(int delay)
{
	if(timer->isActive())
	{
		timer->start(100 - delay);
	}
	else
	{
		timer->setInterval(100 - delay);
	}
	for(int i = 0; i < KittingCell::numOfPartSorterUnits; i++) {
		partSorterUnitsAgents[i]->lane1Agent->setFactorySpeed(100 - delay);
		partSorterUnitsAgents[i]->lane2Agent->setFactorySpeed(100 - delay);
	}
	factoryScene->setTimerDelay(100 - delay);

}

void KittingCell::handleMakePresetKitButton()
{
	int numKits = ui.numKitsToBuildLineEdit->text().toInt();

	if(numKits == 0)
	{
		ui.numKitsToBuildLineEdit->clear();
	}

	for(int i = 0; i < numKits; i++)
	{
		QString kitText = ui.kitSelectorComboBox->currentText();

		KitRecipe *newKitRecipe = this->generateKitRecipeFromString(kitText);
		//qDebug()<<newKitRecipe.partsNeeded[0];
		this->FCSAgent->msgHereIsKitOrder( newKitRecipe);
	}

	//this->testKitRobotGoodKit();
	//this->testKitRobotBadKit();
}

void KittingCell::handleMakeCustomKitButton()
{
	int numKits = ui.numKitsToBuildLineEdit->text().toInt();

	if(numKits == 0)
	{
		ui.numKitsToBuildLineEdit->clear();
	}

	for(int i = 0; i < numKits; i++)
	{

		QString kitTextString;

		if (ui.comboBoxPart1->currentText() == "Space")
			kitTextString += "_";
		else
			kitTextString += ui.comboBoxPart1->currentText();
		if (ui.comboBoxPart2->currentText() == "Space")
			kitTextString += "_";
		else
			kitTextString += ui.comboBoxPart2->currentText();
		if (ui.comboBoxPart3->currentText() == "Space")
			kitTextString += "_";
		else
			kitTextString += ui.comboBoxPart3->currentText();
		if (ui.comboBoxPart4->currentText() == "Space")
			kitTextString += "_";
		else
			kitTextString += ui.comboBoxPart4->currentText();
		if (ui.comboBoxPart5->currentText() == "Space")
			kitTextString += "_";
		else
			kitTextString += ui.comboBoxPart5->currentText();
		if (ui.comboBoxPart6->currentText() == "Space")
			kitTextString += "_";
		else
			kitTextString += ui.comboBoxPart6->currentText();
		if (ui.comboBoxPart7->currentText() == "Space")
			kitTextString += "_";
		else
			kitTextString += ui.comboBoxPart7->currentText();
		if (ui.comboBoxPart8->currentText() == "Space")
			kitTextString += "_";
		else
			kitTextString += ui.comboBoxPart8->currentText();

		KitRecipe *newKitRecipe = this->generateKitRecipeFromString(kitTextString);
		//qDebug()<<newKitRecipe.partsNeeded[0];
		FCSAgent->msgHereIsKitOrder(newKitRecipe);
	}
}

KitRecipe* KittingCell::generateKitRecipeFromString(QString inputText)
{
	KitRecipe *newKitRecipe = new KitRecipe();

	for( int i = 0; i < inputText.length(); i++ )
	{
		QChar qLetter = inputText.at(i).toUpper(); 
		char letter = qLetter.toAscii();

		PartType partType;

		switch(letter)
		{
			case 'A':
				partType = PartType::A;
				break;
			case 'B':
				partType = PartType::B;
				break;
			case 'C':
				partType = PartType::C;
				break;
			case 'D':
				partType = PartType::D;
				break;
			case 'E':
				partType = PartType::E;
				break;
			case 'F':
				partType = PartType::F;
				break;
			case 'G':
				partType = PartType::G;
				break;
			case 'H':
				partType = PartType::H;
				break;
			case 'I':
				partType = PartType::I;
				break;
			case 'J':
				partType = PartType::J;
				break;
			case 'K':
				partType = PartType::K;
				break;
			case 'L':
				partType = PartType::L;
				break;
			case 'M':
				partType = PartType::M;
				break;
			case 'N':
				partType = PartType::N;
				break;
			case 'O':
				partType = PartType::O;
				break;
			case 'P':
				partType = PartType::P;
				break;
			case 'Q':
				partType = PartType::Q;
				break;
			case 'R':
				partType = PartType::R;
				break;
			case 'S':
				partType = PartType::S;
				break;
			case 'T':
				partType = PartType::T;
				break;
			case 'U':
				partType = PartType::U;
				break;
			case 'V':
				partType = PartType::V;
				break;
			case 'W':
				partType = PartType::W;
				break;
			case 'X':
				partType = PartType::X;
				break;
			case 'Y':
				partType = PartType::Y;
				break;
			case 'Z':
				partType = PartType::Z;
				break;
			case '_':
				partType = PartType::SPACE;
				break;
			default:
				partType = PartType::EMPTY;
				break;
		}
		//newKitRecipe.partsNeeded[i] = partType;
		newKitRecipe->partsNeeded.push_back(partType);

	}	//end for loop 0-7

	return newKitRecipe;
}

void KittingCell::handlePurgeButton()
{
	QString indexQStr = ui.purgeOptionsComboBox->currentText();
	int index = indexQStr.toInt();
	int psuIndex = 0;

	if(index < 2)
		psuIndex = 0;
	else if(index < 4)
		psuIndex = 1;
	else if(index < 6)
		psuIndex = 2;
	else
		psuIndex = 3;

	NestAgent *currentAgent;
	GUINest *currentNest = nests[index];

	if((index) % 2 == 0)	//if lane number is even because index is the number
		currentAgent = this->partSorterUnitsAgents[psuIndex]->nest1Agent;
	else
		currentAgent = this->partSorterUnitsAgents[psuIndex]->nest2Agent;

	//Do whatever needs to be done to purge here, current nest's gui and agent are available
	currentNest->togglePurge();
	//currentAgent->msgPleaseGetParts(PartType::X);
}

//Methods to handle breaking things
void KittingCell::handleFeederBreakSelectComboBoxStateChanged(QString newText)
{
	QString indexQStr = ui.feederBreakSelectComboBox->currentText();
	int index = indexQStr.toInt() - 1;

	if(this->partSorterUnitsAgents[index]->feederAgent->isBroken)
		ui.feederBreakButton->setText("Fix");
	else
		ui.feederBreakButton->setText("Break");
}

void KittingCell::handleLaneBreakSelectComboBoxStateChanged(QString newText)
{
	QString indexQStr = ui.laneBreakSelectComboBox->currentText();
	int index = indexQStr.toInt() - 1;


	int psuIndex;

	if(index < 2)
		psuIndex = 0;
	else if(index < 4)
		psuIndex = 1;
	else if(index < 6)
		psuIndex = 2;
	else
		psuIndex = 3;

	if((index) % 2 == 0)	//if lane number is even because index is the number - 1
	{
		if(this->partSorterUnitsAgents[psuIndex]->lane1Agent->isBroken)
			ui.laneBreakButton->setText("Fix");
		else
			ui.laneBreakButton->setText("Break");
	}
	else
	{
		if(this->partSorterUnitsAgents[psuIndex]->lane2Agent->isBroken)
			ui.laneBreakButton->setText("Fix");
		else
			ui.laneBreakButton->setText("Break");
	}
}

void KittingCell::handleNestBreakSelectComboBoxStateChanged(QString newText)
{
	QString indexQStr = ui.nestBreakSelectComboBox->currentText();
	//QString indexQStr = newText;

	int index = indexQStr.toInt() - 1;


	int psuIndex;

	if(index < 2)
		psuIndex = 0;
	else if(index < 4)
		psuIndex = 1;
	else if(index < 6)
		psuIndex = 2;
	else
		psuIndex = 3;

	if((index) % 2 == 0)	//if lane number is even because index is the number - 1
	{
		if(this->partSorterUnitsAgents[psuIndex]->nest1Agent->isBroken)
			ui.nestBreakButton->setText("Fix");
		else
			ui.nestBreakButton->setText("Break");
	}
	else
	{
		if(this->partSorterUnitsAgents[psuIndex]->nest2Agent->isBroken)
			ui.nestBreakButton->setText("Fix");
		else
			ui.nestBreakButton->setText("Break");
	}
}

void KittingCell::handleCameraBreakSelectComboBoxStateChanged(QString newText)
{
	QString indexQStr = ui.cameraBreakSelectComboBox->currentText();
	
	int index = indexQStr.toInt() - 1;

	if(index < 4)
	{
		if(this->partSorterUnitsAgents[index]->cameraAgent->isBroken)
			ui.cameraBreakButton->setText("Fix");
		else
			ui.cameraBreakButton->setText("Break");
	}
	else
	{
		if(inspectorAgent->isBroken)
			ui.cameraBreakButton->setText("Fix");
		else
			ui.cameraBreakButton->setText("Break");
	}
}

void KittingCell::handleGantryBreakButton()
{
	if(!gantryAgent->isBroken)
		ui.gantryBreakButton->setText("Fix");
	else
		ui.gantryBreakButton->setText("Break");

	gantryAgent->msgToggleBreak();
}

void KittingCell::handleGantryExplodeButton()
{
	if (!gantryAgent->isBroken)
	{
		gantryAgent->msgExplode();
		handleGantryBreakButton();
	}
}

void KittingCell::handleConveyorsBreakButton()
{
	if(!inConveyorAgent->isBroken) {
		ui.conveyorsBreakButton->setText("Fix");
	} else {
		ui.conveyorsBreakButton->setText("Break");
	}
	this->inConveyorAgent->msgToggleBreak();
	this->outGoodConveyorAgent->msgToggleBreak();
	this->outBadConveyorAgent->msgToggleBreak();
}

void KittingCell::handleFeederBreakButton()
{
	QString indexQStr = ui.feederBreakSelectComboBox->currentText();
	int index = indexQStr.toInt() - 1;

	if(!this->partSorterUnitsAgents[index]->feederAgent->isBroken)
		ui.feederBreakButton->setText("Fix");
	else
		ui.feederBreakButton->setText("Break");

	this->partSorterUnitsAgents[index]->feederAgent->msgToggleBreak();
}

void KittingCell::handleLaneBreakButton()
{
	QString indexQStr = ui.laneBreakSelectComboBox->currentText();
	int index = indexQStr.toInt() - 1;


	int psuIndex;

	if(index < 2)
		psuIndex = 0;
	else if(index < 4)
		psuIndex = 1;
	else if(index < 6)
		psuIndex = 2;
	else
		psuIndex = 3;

	if((index) % 2 == 0)	//if lane number is even because index is the number - 1
	{
		if(!this->partSorterUnitsAgents[psuIndex]->lane1Agent->isBroken)
			ui.laneBreakButton->setText("Fix");
		else
			ui.laneBreakButton->setText("Break");

		this->partSorterUnitsAgents[psuIndex]->lane1Agent->msgToggleBreak();
	}
	else
	{
		if(!this->partSorterUnitsAgents[psuIndex]->lane2Agent->isBroken)
			ui.laneBreakButton->setText("Fix");
		else
			ui.laneBreakButton->setText("Break");

		this->partSorterUnitsAgents[psuIndex]->lane2Agent->msgToggleBreak();
	}


}

void KittingCell::handleLaneJamButton()
{
	QString indexQStr = ui.laneJamSelectComboBox->currentText();
	int index;

	if(indexQStr == "Lane 1")
		index = 0;
	else if(indexQStr == "Lane 2")
		index = 1;
	else if(indexQStr == "Lane 3")
		index = 2;
	else if(indexQStr == "Lane 4")
		index = 3;
	else if(indexQStr == "Lane 5")
		index = 4;
	else if(indexQStr == "Lane 6")
		index = 5;
	else if(indexQStr == "Lane 7")
		index = 6;
	else if(indexQStr == "Lane 8")
		index = 7;
	else
		index = 0;

	lanes[index]->DoJamLane();
}

void KittingCell::handleUnJamButton()
{
	for(int i = 0; i < lanes.size(); i++)
	{
		this->lanes[i]->DoClearJam();
	}
}

void KittingCell::handleLanePartJumpButton()
{
	QString indexQStr = ui.partJumpLaneSelectComboBox->currentText();
	int index;

	if(indexQStr == "Lane 1")
		index = 0;
	else if(indexQStr == "Lane 2")
		index = 1;
	else if(indexQStr == "Lane 3")
		index = 2;
	else if(indexQStr == "Lane 4")
		index = 3;
	else if(indexQStr == "Lane 5")
		index = 4;
	else if(indexQStr == "Lane 6")
		index = 5;
	else if(indexQStr == "Lane 7")
		index = 6;
	else if(indexQStr == "Lane 8")
		index = 7;
	else
		index = 0;

	lanes[index]->JumpLane();
	//TODO
}

void KittingCell::handleNestBreakButton()
{
	QString indexQStr = ui.nestBreakSelectComboBox->currentText();
	int index = indexQStr.toInt() - 1;


	int psuIndex;

	if(index < 2)
		psuIndex = 0;
	else if(index < 4)
		psuIndex = 1;
	else if(index < 6)
		psuIndex = 2;
	else
		psuIndex = 3;

	if((index) % 2 == 0)	//if lane number is even because index is the number - 1
	{
		if(!this->partSorterUnitsAgents[psuIndex]->nest1Agent->isBroken)
			ui.nestBreakButton->setText("Fix");
		else
			ui.nestBreakButton->setText("Break");

		this->partSorterUnitsAgents[psuIndex]->nest1Agent->msgToggleBreak();
	}
	else
	{
		if(!this->partSorterUnitsAgents[psuIndex]->nest2Agent->isBroken)
			ui.nestBreakButton->setText("Fix");
		else
			ui.nestBreakButton->setText("Break");
		
		this->partSorterUnitsAgents[psuIndex]->nest2Agent->msgToggleBreak();
	}
}

void KittingCell::handleCameraBreakButton()
{
	QString indexQStr = ui.cameraBreakSelectComboBox->currentText();
	
	int index = indexQStr.toInt() - 1;

	if(index < 4)
	{
		if(!this->partSorterUnitsAgents[index]->cameraAgent->isBroken)
			ui.cameraBreakButton->setText("Fix");
		else
			ui.cameraBreakButton->setText("Break");

		this->partSorterUnitsAgents[index]->cameraAgent->msgToggleBreak();
	}
	else
	{
		if(!inspectorAgent->isBroken)
			ui.cameraBreakButton->setText("Fix");
		else
			ui.cameraBreakButton->setText("Break");

		inspectorAgent->msgToggleBreak();
	}
}

void KittingCell::handlePartRobotBreakButton()
{
	if(!partRobotAgent->isBroken)
		ui.partRobotBreakButton->setText("Fix");
	else
		ui.partRobotBreakButton->setText("Break");

	this->partRobotAgent->msgToggleBreak();
}

void KittingCell::handleKitRobotBreakButton()
{
	if(!kitRobotAgent->isBroken)
		ui.kitRobotBreakButton->setText("Fix");
	else
		ui.kitRobotBreakButton->setText("Break");

	this->kitRobotAgent->msgToggleBreak();
}

void KittingCell::handleFCSBreakButton()
{
	if(!FCSAgent->isBroken)
		ui.FCSBreakButton->setText("Fix");
	else
		ui.FCSBreakButton->setText("Break");

	this->FCSAgent->msgToggleBreak();
}

void KittingCell::handlePartCleanUpButton()
{
	roomba->doCleanUpNextPart();
}


void KittingCell::testKitRobotGoodKit() {
	Kit* kit = new Kit(0,0, this->factoryScene);
	kit->partTypesNeeded.push_back( PartType::A);
	kit->partTypesNeeded.push_back( PartType::B);
	kit->partTypesNeeded.push_back( PartType::C);

	kit->addPart(new Part(0,0,PartType::A, factoryScene));
	kit->addPart(new Part(0,0,PartType::B, factoryScene));
	kit->addPart(new Part(0,0,PartType::C, factoryScene));

	table->insert(kit, 0);
	kitRobotAgent->msgKitFinished(kit);
}

void KittingCell::testKitRobotBadKit(){
	Kit* kit = new Kit(0,0, this->factoryScene);
	kit->partTypesNeeded.push_back( PartType::A);
	kit->partTypesNeeded.push_back( PartType::B);
	kit->partTypesNeeded.push_back( PartType::C);

	kit->addPart(new Part(0,0,PartType::A, factoryScene));

	table->insert(kit, 1);
	kitRobotAgent->msgKitFinished(kit);
}